home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 2 / MacMania 2.toast / Demo's / Music⁄Sounds / BeepSay 1.0.1 / cdev.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-22  |  18.4 KB  |  789 lines  |  [TEXT/MPS ]

  1. /******************************************************************************
  2. **
  3. **  Folder Name:    BS
  4. **     File Name:    cdev.c
  5. **
  6. **   Copyright:    © 1993 by Siren Enterprises, all rights reserved.
  7. **
  8. **   Description:    Lil´ BeepSay control pannel, used to configure Lil´ BeepSay.
  9. **
  10. *******************************************************************************
  11. **                       A U T H O R   I D E N T I T Y
  12. *******************************************************************************
  13. **
  14. **    Initials    Name
  15. **    --------    -----------------------------------------------
  16. **    KW            Ken Wieschhoff
  17. **
  18. *******************************************************************************
  19. **                      R E V I S I O N   H I S T O R Y
  20. *******************************************************************************
  21. **
  22. **      Date        Time    Author    Description
  23. **    --------    -----    ------    ---------------------------------------------
  24. **    06/22/93    15:13    kw        1+ Add animate lips option
  25. **    05/17/93    21:39    KW        Original
  26. **
  27. ******************************************************************************/
  28.  
  29. #include    <Traps.h>
  30. #include    <GestaltEqu.h>
  31. #include    <Notification.h>
  32. #include    <PLStringFuncs.h>
  33. #include    <Quickdraw.h>
  34. #include    <Packages.h>
  35. #include    <errors.h>
  36. #include    <Controls.h>
  37. #include    <Menus.h>
  38. #include    <Devices.h>
  39. #include    "Resident.h"
  40. #include    "Preferences.h"
  41. #include    "Utilities.h"
  42.  
  43.  
  44.  
  45. // •• Main Dialog items
  46. #define    kOnButton        1
  47. #define    kOffButton        2
  48. #define    kVoiceMenu        4
  49. #define    kText            5
  50. #define    kTryText        6
  51. #define    kShowIcon        7
  52. #define    kDecorativeIcon    8
  53. #define    kNoOverLap        9
  54. #define    kFaster            10
  55. #define kSlower            11
  56. #define    kLower            12
  57. #define    kHigher            13
  58. #define    kAnimate        14
  59.  
  60. #define WhereAmI(a) 
  61.  
  62. //•• Protoypes
  63. OSErr DoInitialization(DialogPtr    CPDialog,
  64.                          short            numItems,
  65.                          long            *cdevStorage);
  66.  
  67. void DoClose(DialogPtr        CPDialog, short numItems, long    *cdevStorage);
  68.  
  69. void DoItemHit(DialogPtr        CPDialog,
  70.                short            item,
  71.                short            numItems,
  72.                EventRecord        *theEvent,
  73.                long                *cdevStorage);
  74.  
  75. void DoUpdate(    DialogPtr    CPDialog,
  76.                 short        numItems,
  77.                 long        *cdevStorage);
  78.  
  79. OSErr DoActivate(DialogPtr        CPDialog,
  80.                 short            numItems,
  81.                 long            *cdevStorage);
  82.  
  83. void DoDeactivate(long    *cdevStorage);
  84.  
  85. OSErr WritePreferences(PreferencesHdl preferences);
  86. pascal void ShowStr( StringPtr str);
  87. pascal void ShowStrNum( StringPtr str, OSErr error);
  88.  
  89. pascal void SpeakAndShowText(DialogPtr    CPDialog,
  90.                             short        numItems,
  91.                             long        *cdevStorage,
  92.                             StringPtr    theText,
  93.                             Boolean        animate);
  94.  
  95. //•• Used to simulate speaking when text phrases are spoken
  96. struct callbackinfo {
  97.     DialogPtr    itsDialog;
  98.     CIconHandle    open;
  99.     CIconHandle    close;
  100.     Rect        itsRect;
  101. };
  102.  
  103. typedef struct callbackinfo callbackinfo;
  104. typedef callbackinfo *callbackinfoPtr, **callbackinfoHdl;
  105.  
  106.  
  107. //•• Main entry point
  108. pascal long MAIN(    short            message,
  109.                     short            item,
  110.                     short            numItems,
  111.                     short            /* CPanelID */,
  112.                     EventRecord        *theEvent,
  113.                     long            cdevStorage,
  114.                     DialogPtr        CPDialog)
  115.  {
  116.      OSErr    err;
  117.     
  118.     if( message == macDev) {
  119.         return( 1);                                // we work on every machine
  120.     }
  121.     
  122.     if (cdevStorage == 0) 
  123.         return (cdevStorage);    // exit immediately, due to previous error
  124.  
  125.  
  126.         switch( message) {
  127.             case initDev:
  128.                 err = DoInitialization(CPDialog, numItems, &cdevStorage);
  129.                 break;
  130.                 
  131.             case closeDev:
  132.                 DoClose(CPDialog,   numItems, &cdevStorage);
  133.  
  134.                 break;
  135.                 
  136.             case hitDev:
  137.                 DoItemHit(CPDialog, item, numItems, theEvent, &cdevStorage);
  138.                 break;
  139.                 
  140.             case nulDev:
  141.                 break;
  142.  
  143.             case updateDev:
  144.                 DoUpdate(CPDialog, numItems, &cdevStorage);
  145.                 break;
  146.  
  147.             case activDev:
  148.                 err = DoActivate(CPDialog, numItems, &cdevStorage);
  149.                 break;
  150.  
  151.             case deactivDev:
  152.                 DoDeactivate(  &cdevStorage);
  153.  
  154.                 break;
  155.  
  156.             case keyEvtDev:
  157.                 break;
  158.  
  159.             case undoDev:
  160.             case cutDev:
  161.             case copyDev:
  162.             case pasteDev:
  163.             case clearDev:
  164.                 break;
  165.         }
  166.         
  167.     
  168.     return( cdevStorage);
  169. }
  170.  
  171.  
  172. pascal void ShowStr( StringPtr str)
  173. {
  174.     ParamText(str, "\p","\p","\p");
  175.     (void) Alert(129, nil);
  176. }
  177.  
  178. pascal void ShowStrNum( StringPtr str, OSErr error)
  179. {
  180.     Str255    errorText;
  181.     
  182.     NumToString((long) error, errorText);
  183.     ParamText( str, "\p. Error = ", errorText, "\p");
  184.     (void) Alert(129, nil);
  185. }
  186.  
  187.  
  188.  
  189. TrapType GetTrapType( short    theTrap)
  190. {
  191.     if ( theTrap & 0x0800)
  192.         return ToolTrap;
  193.     else
  194.         return OSTrap;
  195. }
  196.  
  197.  
  198.  
  199. Boolean HitCheckBox(DialogPtr    dlg,
  200.                      short        item)
  201. {
  202.   short            itemtype;
  203.   ControlHandle    hand;
  204.   Rect            box;
  205.  
  206.   GetDItem(dlg, item, &itemtype, (Handle*)&hand, &box);
  207.   if (GetCtlValue(hand) == 0)
  208.     {
  209.       SetCtlValue(hand, 1);
  210.       return(true);
  211.     }
  212.   else
  213.     {
  214.       SetCtlValue(hand, 0);
  215.       return(false);
  216.     }
  217. }
  218.  
  219. Boolean GetRadioValue(DialogPtr    dlg, short    item)
  220. {
  221.   short            itemtype;
  222.   ControlHandle    hand;
  223.   Rect            box;
  224.  
  225.   GetDItem(dlg, item, &itemtype, (Handle*)&hand, &box);
  226.   if (GetCtlValue(hand) == 0)
  227.     {
  228.       return(false);
  229.     }
  230.   else
  231.     {
  232.       return(true);
  233.     }
  234. }
  235.  
  236.  
  237. void HitRadioButton(DialogPtr    dlg,
  238.                     short         item,
  239.                     short         logicalID,
  240.                     short         logicalStart,
  241.                     short         logicalEnd)
  242. {
  243.   short            itemtype;
  244.   ControlHandle    hand;
  245.   Rect            box;
  246.   short            startID;
  247.   short            endID;
  248.   short            numItems;
  249.   short            loop;
  250.  
  251.   // Get the start and end ID's from the logicals 
  252.   
  253.   numItems = item - logicalID;
  254.   startID = logicalStart + numItems;
  255.   endID = logicalEnd + numItems;
  256.   
  257.   // Clear all the radio buttons in the group
  258.   
  259.   for (loop = startID; loop <= endID; ++loop)
  260.     {
  261.       GetDItem(dlg, loop, &itemtype, (Handle*)&hand, &box);
  262.       if (GetCtlValue(hand) != 0) SetCtlValue(hand, 0);        // set control only when necessary
  263.     }
  264.     
  265.   // Set the item hit
  266.     
  267.   GetDItem(dlg, item, &itemtype, (Handle*)&hand, &box);
  268.   if (GetCtlValue(hand) != 1) SetCtlValue(hand, 1);            // set control only when necessary
  269. }
  270.  
  271.  
  272.  
  273. OSErr DoInitialization(DialogPtr    CPDialog,
  274.                          short            numItems,
  275.                          long            *cdevStorage)
  276. {
  277. #pragma unused ( CPDialog, numItems)
  278.  
  279.     OSErr                err;
  280.     PreferencesHdl        thePreferences;
  281.     short                menuItem = 1;
  282.     long                result;
  283.  
  284.     
  285.     WhereAmI("\p DoInitialization");
  286.     
  287.     err = Gestalt( gestaltSpeechAttr, &result);
  288.     if ((err != noErr) || !(result &  (1 << gestaltSpeechMgrPresent))) {
  289.         ShowStr("\p No Speech Manager Installed!");
  290.         *cdevStorage = cdevGenErr;
  291.         return(cdevGenErr);
  292.     }
  293.  
  294.  
  295.     // Read the preferences from disk.
  296.     err = _ReadPreferences( &thePreferences, kBeepSayPrefs);
  297.     
  298.     if (err != noErr ) {
  299.         ShowStrNum("\p Couldn't read/create preferences!", err);
  300.         *cdevStorage = cdevGenErr;
  301.         return(cdevGenErr);
  302.     }
  303.  
  304.     *cdevStorage = (long *) thePreferences;
  305.  
  306. }
  307.  
  308.  
  309.  
  310. void DoDeactivate(long    *cdevStorage)
  311. {
  312. #pragma unused ( cdevStorage)
  313. }
  314.  
  315. void DoClose(DialogPtr        CPDialog, short numItems, long    *cdevStorage)
  316. {
  317.     short            itemType;
  318.     Handle            itemHandle;
  319.     Rect            box;
  320.     PreferencesHdl    thePreferences = (PreferencesHdl)*cdevStorage;;
  321.  
  322.  
  323.     GetDItem( CPDialog, numItems + kText, &itemType, &itemHandle, &box);
  324.     GetIText( itemHandle, (**thePreferences).theText);
  325.  
  326.     // Unconditionally write to preferences.
  327.     WritePreferences( thePreferences);
  328. }
  329.  
  330.  
  331. pascal void PlotTheIcon(DialogPtr itsDialog, CIconHandle theIcon, Rect *itsRect)
  332. {
  333.  
  334.     // Support routine to simulate speaking when text phrases are spoken.
  335.  
  336.     GrafPtr            oldPort;        
  337.  
  338.     if ( theIcon) {
  339.  
  340.         GetPort( &oldPort);
  341.         SetPort( itsDialog);
  342.         
  343.         PlotCIcon(itsRect, theIcon);
  344.  
  345.         SetPort( oldPort);
  346.     }
  347. }
  348.  
  349. pascal void EndOfTextCallback( SpeechChannel channel, long refCon)
  350. {
  351. #    pragma unused( channel)
  352.     callbackinfoPtr    itsInfoPtr = (callbackinfoPtr) refCon;
  353.  
  354.     // Shut your mouth, dude!
  355.     PlotTheIcon(itsInfoPtr->itsDialog, itsInfoPtr->close, &itsInfoPtr->itsRect);
  356.  
  357. }
  358.  
  359. pascal void PhonemeCallBack( SpeechChannel channel, long refCon, 
  360.                 short phonemeOpcode)
  361. {
  362. #    pragma unused(channel, phonemeOpcode )
  363.     callbackinfoPtr    itsInfoPtr = (callbackinfoPtr) refCon;
  364.  
  365.     // Open and then close the mouth for each phoneme.
  366.     // •• Note that doing lengthy graphic operation here may introduce a "stutter"
  367.     // while text phrases are spoken. Use small icons.
  368.     PlotTheIcon(itsInfoPtr->itsDialog, itsInfoPtr->close, &itsInfoPtr->itsRect);
  369.     PlotTheIcon(itsInfoPtr->itsDialog, itsInfoPtr->open, &itsInfoPtr->itsRect);
  370.  
  371. }
  372.  
  373. void DoItemHit(DialogPtr        CPDialog,
  374.                short            item,
  375.                short            numItems,
  376.                EventRecord        *theEvent,
  377.                long                *cdevStorage)
  378. {
  379. #pragma unused( theEvent)
  380.  
  381.     short            itemType;
  382.     Handle            itemHandle;
  383.     Rect            box;
  384.     PreferencesHdl    thePreferences = (PreferencesHdl)*cdevStorage;
  385.     short            itsVoice;
  386.     Str255            theText;
  387.     short            logicalID;
  388.     OSErr            err = -214;
  389.     StringPtr        aboutText = 
  390.         "\p[[rate 150]]Version 1 point 0 point 1. Copyright Siren Enterprises. Narly, dude!";
  391.     SpeechChannel    itsChannel;
  392.     long            timeOut;
  393.     Boolean            animate = (**thePreferences).animate;
  394.     
  395.     logicalID = item - numItems;
  396.     
  397.     switch (logicalID)
  398.     {
  399.         case kOnButton:    
  400.         case kOffButton:    
  401.             (**thePreferences).on_off = (logicalID == kOnButton);
  402.             HitRadioButton(CPDialog, item, item, kOnButton, kOffButton);
  403.           break;
  404.         
  405.         
  406.         case kVoiceMenu :
  407.     
  408.             GetDItem( CPDialog, item, &itemType, &itemHandle, &box);
  409.             itsVoice = GetCtlValue( (ControlHandle)itemHandle);
  410.             err = GetIndVoice(itsVoice, &(**thePreferences).theVoice);
  411.             if ( err != noErr) {
  412.                 ShowStrNum("\p Could not get indicated voice!", err);
  413.                 return;
  414.             }
  415.                 
  416.             // Try for no more than 3 seconds to get a new speech channel.
  417.             timeOut = TickCount() + 180;
  418.             err = -1;
  419.             while (( err != noErr)  && (TickCount() < timeOut))
  420.                 err = NewSpeechChannel( &(**thePreferences).theVoice, &itsChannel);
  421.         
  422.             // Reset the default rate and pitch.
  423.             if ( err == noErr) {
  424.                 (void) GetSpeechPitch( itsChannel, &(**thePreferences).thePitch);
  425.                 (void) GetSpeechRate( itsChannel, &(**thePreferences).theRate);
  426.                 (void) DisposeSpeechChannel( itsChannel);
  427.             }
  428.             
  429.             break;
  430.             
  431.         case kTryText :
  432.             GetDItem( CPDialog, numItems + kText, &itemType, &itemHandle, &box);
  433.             GetIText( itemHandle, theText);
  434.  
  435.             SpeakAndShowText(CPDialog, numItems, cdevStorage, theText, animate);
  436.             break;
  437.             
  438.         case kShowIcon:
  439.             (**thePreferences).iconAtStartup = HitCheckBox(CPDialog, item);
  440.             break;
  441.             
  442.         // Speak text synchronously.
  443.         case kNoOverLap:
  444.             (**thePreferences).onlyPlayOne = HitCheckBox(CPDialog, item);
  445.             break;
  446.         
  447.         // Play the "about" sound.
  448.         case kDecorativeIcon: 
  449.             SpeakAndShowText(CPDialog, numItems, cdevStorage, aboutText, animate);
  450.             break;
  451.             
  452.         // Speak phrase faster.
  453.         case kFaster: 
  454.             (**thePreferences).theRate += (10 << 16);
  455.             GetDItem( CPDialog, numItems + kText, &itemType, &itemHandle, &box);
  456.             GetIText( itemHandle, theText);
  457.  
  458.             SpeakAndShowText(CPDialog, numItems, cdevStorage, theText, animate);
  459.  
  460.             break;
  461.             
  462.         // Speak phrase slower.
  463.         case kSlower: 
  464.             (**thePreferences).theRate -= (10 << 16);
  465.             GetDItem( CPDialog, numItems + kText, &itemType, &itemHandle, &box);
  466.             GetIText( itemHandle, theText);
  467.  
  468.             SpeakAndShowText(CPDialog, numItems, cdevStorage, theText, animate);
  469.             break;
  470.             
  471.         // Lower the pitch
  472.         case kLower: 
  473.             (**thePreferences).thePitch -= (1 << 16);
  474.             GetDItem( CPDialog, numItems + kText, &itemType, &itemHandle, &box);
  475.             GetIText( itemHandle, theText);
  476.  
  477.             SpeakAndShowText(CPDialog, numItems, cdevStorage, theText, animate);
  478.             break;
  479.         
  480.         // Raise the pitch
  481.         case kHigher: 
  482.             (**thePreferences).thePitch += (1 << 16);
  483.             GetDItem( CPDialog, numItems + kText, &itemType, &itemHandle, &box);
  484.             GetIText( itemHandle, theText);
  485.  
  486.             SpeakAndShowText(CPDialog, numItems, cdevStorage, theText, animate);
  487.             break;
  488.  
  489.         case kAnimate:
  490.             (**thePreferences).animate = HitCheckBox(CPDialog, item);
  491.             break;
  492.             
  493.         
  494.     } // switch 
  495.  
  496. }  // DoItemHit
  497.  
  498.  
  499.  
  500. void DoUpdate(    DialogPtr    CPDialog,
  501.                 short        numItems,
  502.                 long        *cdevStorage)
  503. {
  504. #pragma unused( CPDialog, numItems, cdevStorage)
  505.  
  506. pascal void SpeakAndShowText(DialogPtr    CPDialog,
  507.                             short        numItems,
  508.                             long        *cdevStorage,
  509.                             StringPtr    theText,
  510.                             Boolean        animate)
  511. {
  512.     short            itemType;
  513.     Handle            itemHandle;
  514.     Rect            box;
  515.     SpeechChannel    itsChannel;
  516.     OSErr            err = -214;
  517.     callbackinfo    itsInfo;
  518.     long            ourA5;
  519.     PreferencesHdl    thePreferences = (PreferencesHdl)*cdevStorage;
  520.     long            timeOut = TickCount() + 180;
  521.     Boolean            reallyAnimate = animate;
  522.  
  523.     GetDItem( CPDialog, numItems + kDecorativeIcon, &itemType, &itemHandle, &box);
  524.  
  525.     itsInfo.itsDialog    = CPDialog;
  526.     
  527.     // Get the icons for the open/closed mouth
  528.     if ( reallyAnimate) {
  529.         itsInfo.open         = GetCIcon( 2000);
  530.         itsInfo.close         = GetCIcon( 1000);
  531.     }
  532.     else {
  533.         itsInfo.open         = nil;
  534.         itsInfo.close         = nil;
  535.     }
  536.     itsInfo.itsRect     = box;
  537.  
  538.     // Lock 'em.
  539.     if (itsInfo.open != nil)
  540.         HLock( (Handle) itsInfo.open);
  541.     else
  542.         reallyAnimate = false; // In case we didn't get the icons
  543.         
  544.     if (itsInfo.close != nil)
  545.         HLock( (Handle) itsInfo.close);
  546.     else
  547.         reallyAnimate = false;
  548.  
  549.     // Try for no more than 3 seconds to get a new speech channel.
  550.     while (( err != noErr)  && (TickCount() < timeOut))
  551.         err = NewSpeechChannel( &(**thePreferences).theVoice, &itsChannel);
  552.  
  553.     if ( err != noErr) {
  554.         ShowStrNum("\p Could not get speech channel!", err);
  555.         goto ErrExit;
  556.     }
  557.         
  558.     (void)SetSpeechPitch( itsChannel, (**thePreferences).thePitch);
  559.     (void)SetSpeechRate( itsChannel, (**thePreferences).theRate);
  560.  
  561.     // Set the reference constant to point to my struct.
  562.     if ( reallyAnimate ) {
  563.         err = SetSpeechInfo( itsChannel, soRefCon, &itsInfo);
  564.     
  565.         if ( err != noErr) {
  566.             ShowStrNum("\p Could not set speech info!", err);
  567.             goto ErrExit;
  568.         }
  569.     }
  570.     
  571.     // Set the A5 to use when calling my callbacks.
  572.     if ( reallyAnimate ) {
  573.         ourA5 = SetCurrentA5();
  574.         err = SetSpeechInfo( itsChannel, soCurrentA5, &ourA5);
  575.     
  576.         if ( err != noErr) {
  577.             (void)DisposeSpeechChannel( itsChannel);
  578.             ShowStrNum("\p Could not set speech info!", err);
  579.             goto ErrExit;
  580.         }
  581.     }
  582.     
  583.     // Set the end of text callback.
  584.     if ( reallyAnimate ) {
  585.         err = SetSpeechInfo( itsChannel, soSpeechDoneCallBack, &EndOfTextCallback);
  586.     
  587.         if ( err != noErr) {
  588.             (void)DisposeSpeechChannel( itsChannel);
  589.             ShowStrNum("\p Could not set speech info!", err);
  590.             goto ErrExit;
  591.         }
  592.     }
  593.     
  594.     // Set the end of word callback.
  595.     if ( reallyAnimate ) {
  596.         err = SetSpeechInfo( itsChannel, soPhonemeCallBack, &PhonemeCallBack);
  597.     
  598.         if ( err != noErr) {
  599.             (void)DisposeSpeechChannel( itsChannel);
  600.             ShowStrNum("\p Could not set speech info!", err);
  601.             goto ErrExit;
  602.         }
  603.     }
  604.     
  605.     // Finally speak the text.
  606.     err = SpeakText( itsChannel, &theText[1], theText[0]);
  607.  
  608.     if ( err != noErr) {
  609.         (void)DisposeSpeechChannel( itsChannel);
  610.         ShowStrNum("\p Could not set speech info!", err);
  611.         goto ErrExit;
  612.     }
  613.         
  614.     while( SpeechBusy() > 0)
  615.         {}    // Wait for the speech to complete.
  616.  
  617.     err = DisposeSpeechChannel( itsChannel);
  618.     
  619.     if ( err != noErr) {
  620.         ShowStrNum("\p Could not dispose channel!", err);
  621.         goto ErrExit;
  622.     }
  623.  
  624. ErrExit:
  625.  
  626.     if (itsInfo.open != nil)
  627.         DisposeCIcon(itsInfo.open);
  628.     if (itsInfo.close != nil)
  629.         DisposeCIcon(itsInfo.close);
  630.  
  631.  
  632.  
  633. }
  634.  
  635.  
  636. OSErr DoActivate(DialogPtr        CPDialog,
  637.                 short            numItems,
  638.                 long            *cdevStorage)
  639. {
  640.     OSErr                err;
  641.     short                i, limit;
  642.     VoiceSpec            TheVoice;
  643.     VoiceDescription    info;
  644.     short                itemType;
  645.     Rect                dRect;
  646.     Handle                dHandle;
  647.     MenuHandle            voiceMenu;
  648.     ControlHandle        cntrl;
  649.     PreferencesHdl        thePreferences = (PreferencesHdl)*cdevStorage;
  650.     short                menuItem = 0;
  651.     
  652.     
  653.     // Get the handle of the voice menu
  654.     GetDItem( CPDialog, kVoiceMenu + numItems, &itemType, (Handle *) &cntrl, &dRect);
  655.     BlockMove( &(**((**cntrl).contrlData)), &voiceMenu, sizeof(MenuHandle));
  656.  
  657.     for ( i = CountMItems(voiceMenu); i > 0; i--)
  658.         DelMenuItem(voiceMenu,1);
  659.  
  660.     // Count the number of voices available.
  661.     err = CountVoices(&limit);
  662.     if (err != noErr ) {
  663.         ShowStrNum("\p No voices available!", err);
  664.         *cdevStorage = cdevGenErr;
  665.         return(cdevGenErr);
  666.     }
  667.  
  668.     // Add each voice to the voice menu.
  669.     for(i = 1; i <= limit; i++)
  670.     {
  671.         err = GetIndVoice(i, &TheVoice);
  672.         if (err != noErr ) {
  673.             ShowStrNum("\p Can't GetIndVoice!", err);
  674.             goto ErrExit;
  675.         }
  676.         err = GetVoiceDescription( &TheVoice, &info, sizeof(VoiceDescription));
  677.         if (err != noErr ) {
  678.             ShowStrNum("\p Can't GetVoiceDescription!", err);
  679.             goto ErrExit;
  680.         }
  681.         AppendMenu(voiceMenu, info.name);
  682.         
  683.         // Save the one in use
  684.         if ( TheVoice == (**thePreferences).theVoice)
  685.             menuItem = i;
  686.  
  687.     }
  688.  
  689.     // Set the default voice along with its speech rate and pitch.
  690.     if ( menuItem == 0) {
  691.         SpeechChannel    itsChannel;
  692.         long    timeOut = TickCount() + 180;
  693.         menuItem = 1;
  694.         err = GetIndVoice(1, &(**thePreferences).theVoice);
  695.  
  696.         if ( err != noErr) {
  697.             err = -1;
  698.             // Try for no more than 3 seconds to get a new speech channel.
  699.             while (( err != noErr)  && (TickCount() < timeOut))
  700.                 err = NewSpeechChannel( &(**thePreferences).theVoice, &itsChannel);
  701.         
  702.             if ( err == noErr) {
  703.                 (void) GetSpeechPitch( itsChannel, &(**thePreferences).thePitch);
  704.                 (void) GetSpeechRate( itsChannel, &(**thePreferences).theRate);
  705.                 (void) DisposeSpeechChannel( itsChannel);
  706.             }
  707.             
  708.         }
  709.     }
  710.         
  711.     // Set the current voice being used.
  712.     SetCtlMax( cntrl, CountMItems( voiceMenu));
  713.     SetCtlValue( cntrl, menuItem);
  714.     
  715.     // Set the on/off radio cluster
  716.     if ((**thePreferences).on_off)
  717.         HitRadioButton(CPDialog, numItems + kOnButton, numItems + kOnButton, kOnButton, kOffButton);
  718.     else
  719.         HitRadioButton(CPDialog, numItems + kOffButton, numItems + kOffButton, kOnButton, kOffButton);
  720.  
  721.     // Set the show icon button
  722.     GetDItem(CPDialog, numItems + kShowIcon, &itemType, &dHandle, &dRect);
  723.     if ( (**thePreferences).iconAtStartup)
  724.         SetCtlValue( (ControlHandle) dHandle, 1);
  725.     else
  726.         SetCtlValue( (ControlHandle) dHandle, 0);
  727.         
  728.     // Set the "play one at a time" button
  729.     GetDItem(CPDialog, numItems + kNoOverLap, &itemType, &dHandle, &dRect);
  730.     if ( (**thePreferences).onlyPlayOne)
  731.         SetCtlValue( (ControlHandle) dHandle, 1);
  732.     else
  733.         SetCtlValue( (ControlHandle) dHandle, 0);
  734.         
  735.     // Set the "play one at a time" button
  736.     GetDItem(CPDialog, numItems + kAnimate, &itemType, &dHandle, &dRect);
  737.     if ( (**thePreferences).animate)
  738.         SetCtlValue( (ControlHandle) dHandle, 1);
  739.     else
  740.         SetCtlValue( (ControlHandle) dHandle, 0);
  741.         
  742.  
  743.     // Set the text in the dialog.
  744.     GetDItem(CPDialog, numItems + kText, &itemType, &dHandle, &dRect);
  745.     SetIText( dHandle, (**thePreferences).theText);
  746.  
  747.     return( noErr);
  748.  
  749. ErrExit:
  750.     if ( *cdevStorage != nil)
  751.         DisposeHandle( (Handle) *cdevStorage);
  752.  
  753.     *cdevStorage = cdevGenErr;
  754.     return(cdevGenErr);
  755.  
  756.  
  757.  
  758. typedef pascal OSErr (*SetPreferencesProcPtr)( void);
  759.  
  760. OSErr WritePreferences(PreferencesHdl preferences)
  761. {
  762.     short                    err;
  763.     SetPreferencesProcPtr     addr = 0x01;
  764.     
  765.     // Write the preferences to disk.    
  766.     err = WriteToPrefs( preferences, kBeepSayPrefs);
  767.     if (err != noErr)
  768.         return ( err);
  769.  
  770.     // Call the Gestalt function which returns a proc pointer to the routine which
  771.     // will update the extensions global variables from this preferences file.
  772.     err = Gestalt( cKBPSAChangedResource,(long *) &addr);
  773.     if (err != noErr) {
  774.  
  775.         ShowStr("\p Lil´ BeepSay is not Installed!");
  776.         return ( noErr);
  777.     }
  778.     
  779.     
  780.     // Make the extensions update themselves.
  781.     err = (*addr)();
  782.         
  783.     return ( err);
  784. }
  785.  
  786.  
  787.